/*
 * SiFiSy - A File System Simulator
 * Copyright (C) 2010  SevenSoft
 *
 * This file is part of SiFiSy.
 *
 * SiFiSy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SiFiSy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SiFiSy.  If not, see <http://www.gnu.org/licenses/>.
 */

package sifisy.newgui;

import java.awt.*;
import javax.swing.*;
import sifisy.core.Model;

/**
 * @author Alberto Longato
 * @version %I%, %G%
 * @createData 12/05/2010
 */
public class InodeSchema extends JPanel {

    private int simId;

    public InodeSchema(int simId){
        this.simId = simId;
    }

        public void drawArea(Graphics g, int x, int y, int lenx, int leny, String lev) {
        g.setColor(Color.blue);
        int space = leny;
        for (int i = 0; i < 3; i++) {
            g.drawString(lev, x - 37, y + 12);
            g.drawRect(x, y, lenx, leny);
            if (i == 2) {
                //ci metto i puntini
                String h = " ° ° ° ";
                g.drawString(h, x + 12, y);
            }
            y = y + space;
        }
    }

    public void drawOtherlev(Graphics g, int x, int y, int lenx, int leny, String lev) {
        g.drawString(lev, x - 50, y + 12);
        g.drawRect(x, y, lenx, leny);
    }

    public void drawInode(Graphics g, int x, int y, int lenx, int leny) {
        //Blocchi di prima indicizzazione
        String lev = "diretti";
        drawArea(g, x, y, lenx, leny , lev);

        //Blocchi di seconda indicizzazione
        y = y + (3 * leny);
        lev = "1° levello";
        drawOtherlev(g, x, y, lenx, leny, lev);

        //Blocchi di seconda indicizzazione
        y = y + leny;
        lev = "2° levello";
        drawOtherlev(g, x, y, lenx, leny, lev);

        //Blocchi di terza indicizzazione
        y = y + leny;
        lev = "3° levello";
        drawOtherlev(g, x, y, lenx, leny, lev);
    }

    public void firstBlock(Graphics g, int x, int y, int lenx, int leny) {
        // info
        leny = 25;
        g.drawString("I-node", x + 5, y - 5);
        g.setColor(Color.red);
        g.drawString("Il numero dei Data Block e' formato dal totale di tutti i blocchi rossi visualizzati", x + (3 * lenx), y - leny);
        g.setColor(Color.blue);
        g.drawRect(x, y, lenx, leny);
        g.setColor(Color.green);
        g.fillRect(x + 1, y + 1, lenx - 1, leny - 1);
        g.setColor(Color.red);
        g.drawString("info", x + (x / 3), y + (y / 3));
        y = y + leny;
        leny = 10;
        drawInode(g, x, y, lenx, leny + 1);
    }

    public void drawArrows(Graphics g, int x, int y, int lenx, int leny) {
        g.setColor(Color.black);
        g.drawLine(x, y, lenx, leny);
        g.drawLine(x, y + 2, lenx, leny);
    }

    public void drawDB(Graphics g, int x, int y, int lenx, int leny, String info) {
        Font font = new Font(Font.SANS_SERIF, Font.BOLD, 9);
        g.setFont(font);
        g.setColor(Color.red);
        g.fillRect(x, y - (leny / 2), lenx - 1, leny);
        g.setColor(Color.white);
        g.drawString(info, x + 1, y - (leny - 1) + 12);
    }

    public void processDirects(Graphics g, int x, int y, int lenx, int leny, int lev) {
        drawArrows(g, x + lenx, y + (leny / 2), x + (2 * lenx), y - (leny / 2));
        drawDB(g, x + (2 * lenx), y - (leny / 2), lenx, leny, "DB");
        if (lev > 1) {
            //genero le altre 2 frecce
            drawArrows(g, x + lenx, y + leny + (leny / 2), x + (2 * lenx), y + leny + (leny / 2) + 1);
            drawDB(g, x + (2 * lenx), y + leny + (leny / 2) + 1, lenx, leny, String.valueOf(lev - 2));

            drawArrows(g, x + lenx, y + 2 * leny + (leny / 2), x + (2 * lenx), y + 2 * leny + (leny / 2) + leny);
            drawDB(g, x + (2 * lenx), y + 2 * leny + (leny / 2) + leny, lenx, leny, "DB");
        }
    }

    public void head(Graphics g, int x, int y, int lenx, int leny, int x1, int y1) {
        drawArrows(g, x, y, x1, y1);
        drawArea(g, x1, y1 - (leny + (leny / 2)), lenx, leny, "");
    }

    public void processFirstLev(Graphics g, int x, int y, int lenx, int leny, int lev) {
        //genero inode di primo levello
        drawArrows(g, x, y + leny, x + lenx, y);
        drawDB(g, x + lenx, y, lenx, leny, "DB");
        if (lev > 2) {
            y = y + leny;
            //genero le altre 2 frecce con DB
            drawArrows(g, x, y + leny, x + lenx, y + leny + 1);
            drawDB(g, x + lenx, y + leny, lenx, leny, String.valueOf(lev - 2));
            y = y + leny;
            drawArrows(g, x, y + leny, x + lenx, y + (2 * leny));
            drawDB(g, x + lenx, y + 2 * leny, lenx, leny, "DB");
        }
    }

    public void central(Graphics g,int x,int y,int lenx,int leny,int x1,int y1,int lev1,int lev,int r2){
         String h = " ° ";
            g.setColor(Color.blue);
            for (int i = 0; i < 7; i++) {
                g.drawString(h, x1 + (lenx / 2) - 5, y1 - leny + (i * 5));
                i++;
            }
            g.drawString("( " + String.valueOf(r2/lev1) + " )", x1 + (lenx / 2) + 10, y + leny / 2);
            drawDB(g, x + (3 * lenx), y, lenx, leny, String.valueOf(r2));
    }
    public void processSecondLev(Graphics g, int x, int y, int lenx, int leny, int lev1, int lev) {
        int x1 = x + lenx;
        int y1 = y - (3 * leny);
        head(g, x, y, lenx, leny, x1, y1);

        x1 = x1 + lenx;
        y1 = y1 - (2 * leny);
        //PRIMO
        int r1 = lev;
           if(r1>lev1) r1=lev1;
        int r3 = lev % lev1;
            if(r3==0) r3=lev1;
        int r2 = (lev -lev1)-r3;

        processFirstLev(g, x1, y1, lenx, leny, r1);
        if (lev > lev1) {
            drawArrows(g, x, y + leny, x + lenx, y + leny + 1);
            y = y + leny;
            y1 = y;
            x1 = x1 - lenx;
            //central
            central(g,x,y,lenx,leny,x1,y1,lev1,lev,r2);

            //ULTIMO
            y = y + leny;
            y1 = y + (3 * leny);
            head(g, x, y, lenx, leny, x1, y1);
            x1 = x1 + lenx;
            y1 = y1 - (2 * leny);
            processFirstLev(g, x1, y1, lenx, leny, r3);
        }
    }

     public void processThirdLev(Graphics g, int x, int y, int lenx, int leny, int lev1, int lev2, int lev) {
        int x1 = x + lenx;
        int y1 = y - (7 * leny);

        int r1 = lev;
            if(r1 > lev1*lev1)
        r1=lev1*lev1;
        int r3= (lev -r1) % r1;
        int r2 = lev - r1 -r3;
        if(r3 == 0 && r2>0 ){
            r2= r2-(lev1*lev1); r3=lev1*lev1;
        }
        //PRIMO
            head(g, x, y, lenx, leny, x1, y1);
            x1 = x1 + lenx;
            y1 = y1 - ( leny);
            processSecondLev(g, x1, y1, lenx, leny, lev1, r1);

        //central
        if (lev > lev2) {
            drawArrows(g, x, y + leny, x + lenx, y + leny + 1);
            central(g,x+2*lenx,y+leny,lenx,leny,x1-lenx,y1+(8*leny),r1,lev,r2);
            drawArrows(g, x+3*lenx, y + leny, x+4*lenx + lenx, y + leny + 1);
            }

        //ULTIMO
            if (lev > r2+r1){
                //ci son ancora DB che puntano
                y=y+2*leny;
                x1 = x1 - lenx;
                y1= y + (7 * leny);
                head(g, x, y, lenx, leny, x1, y1);
                x1 = x1 + lenx;
                y1 = y1 - ( leny);

                processSecondLev(g, x1, y1, lenx, leny, lev1, r3);
                g.setColor(Color.blue);
            }
     }

    public void DrawLegend(Graphics g, int SimId, int InodeDim, String nomefile){
        int x= 570;
        int y =50;
        g.setColor(Color.orange);
        g.drawRect(x , y , 100 , 105 );
        g.fillRect(x , y , 100 , 105 );
        g.setColor(Color.red);
        y=y+10;
        g.drawString("LEGENDA", x + 20, y );
        y=y+20;
        g.setColor(Color.black);
        g.drawString("I-node:", x + 20, y );
        g.setColor(Color.blue);
        g.drawString("'"+nomefile+"'", x + 20, y+15 );
        g.setColor(Color.black);
        y=y+15;
        g.drawString("Dim: "+InodeDim*Model.getSimulation(SimId).getAddressDimension()+" byte", x + 5, y+20 );
        g.drawString("indirizzo: "+Model.getSimulation(SimId).getAddressDimension()+" byte", x + 5, y+40 );
        g.drawString("num indirizzi: "+InodeDim, x + 5, y+60 );
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
       
        int totalBlockFile = (int) (Model.getSimulation(0).getFiles().elementAt(0).getSize() / (Model.getBlockDimension(0) * Math.pow(2, Model.getBlockExponent(0))));
        //inizio frammentazione interna per l'ultimo blocco
        if( Model.getSimulation(0).getFiles().elementAt(0).getSize() % (Model.getBlockDimension(0) * Math.pow(2, Model.getBlockExponent(0))) !=0)
            totalBlockFile++;
        //fine frammentazione interna per l'ultimo blocco
        int maxlev0= Model.getBlockFirstInode(simId);
        int InodeDim = Model.getInodeDimension(simId)/Model.getAddressDimension(simId);
        int totLevel = Model.getAddressLevel(simId);
        
        int lev0 = maxlev0;
        int lev1=0;
        int lev2=0;
        int lev3=0;
        
        DrawLegend(g, simId,InodeDim, Model.getSimulation(simId).getFiles().elementAt(0).getId());

        if(totalBlockFile < maxlev0)
            lev0 = totalBlockFile;
        totalBlockFile = totalBlockFile - lev0;

        if(totalBlockFile > 0){
                lev1 = InodeDim;
                if(totalBlockFile < lev1)
                      lev1= totalBlockFile;
            totalBlockFile = totalBlockFile - lev1;
        }

        if(totalBlockFile > 0){
                lev2 = InodeDim*InodeDim;
                if(totalBlockFile < lev2)
                      lev2= totalBlockFile;
            totalBlockFile = totalBlockFile - lev2;
        }

          if(totalBlockFile > 0){
                lev3 = InodeDim*InodeDim*InodeDim;
                if(totalBlockFile < lev3)
                      lev3= totalBlockFile;
            totalBlockFile = totalBlockFile - lev3;
        }

        //if(totalBlockFile > 0)
          // ; //ERRORE file non ci sta

  
        //INIZIO CODICE
        int x = 55, y = 50, lenx = 50, leny = 10;
        int x1 = 0;
        int y1 = 0;
        Font font = new Font(Font.SANS_SERIF, Font.BOLD, 9);
        g.setFont(font);

        firstBlock(g, x, y, lenx, leny);
        //Diretti
        g.setColor(Color.black);
        g.drawString("BD diretti= " + String.valueOf(lev0), x + (5 * lenx), y - (leny / 2) + 5);
        y = y + 25;

        processDirects(g, x, y, lenx, leny, lev0);
        //Primo
        if (lev1 > 0) {
            g.setColor(Color.black);
            g.drawString("BD da primo indirizzamento= " + String.valueOf(lev1), x + (5 * lenx), y - (leny / 2));
            x = x + lenx;
            y = y + (3 * leny) + (leny / 2);
            x1 = x + (2 * lenx);
            y1 = y + (2 * leny);

            head(g, x, y, lenx, leny, x1, y1);
            x1 = x1 + lenx;
            y1 = y1 - (2 * leny);
            processFirstLev(g, x1, y1, lenx, leny, lev1);
        }
        // Secondo
        if (lev2 > 0) {
            g.setColor(Color.black);
            g.drawString("BD da secondo indirizzamento=  " + String.valueOf(lev2), x + (4 * lenx), y - (2 * leny) - (leny / 2));
            y = y + leny;
            //x = x + lenx;
            x1 = x + (4 * lenx);
            y1 = y + (6 * leny);
            head(g, x, y, lenx, leny, x1, y1);
            x1 = x1 + lenx;
            y1 = y1 - (leny);
            processSecondLev(g, x1, y1, lenx, leny, lev1, lev2);
        }
        // Terzo
        if (lev3 > 0) {
            g.setColor(Color.black);
            g.drawString("BD da terzo indirizzamento= " + String.valueOf(lev3), x + (4 * lenx), y - (2 * leny));
            y = y + leny;
            //x = x + lenx;
            x1 = x + (2 * lenx);
            y1 = y + (27 * leny);
            head(g, x, y, lenx, leny, x1, y1);
            x1 = x1 + lenx;
            y1 = y1 - (leny);
            processThirdLev(g, x1, y1, lenx, leny, lev1, lev2, lev3);
        }
    }
/*
    public static void main(String[] args) {
        InodeSchema disegno = new InodeSchema(0);
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(disegno);
        f.setSize(700, 600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }*/
}
